package com.lc.ibps.platform.rest.login;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.lc.ibps.api.base.cache.ICache;
import com.lc.ibps.api.org.service.IPartyEmployeeMgrService;
import com.lc.ibps.base.core.constants.StringPool;
import com.lc.ibps.base.core.encrypt.EncryptUtil;
import com.lc.ibps.base.core.exception.BaseException;
import com.lc.ibps.base.core.util.AppUtil;
import com.lc.ibps.base.core.util.BeanUtils;
import com.lc.ibps.base.core.util.string.StringUtil;
import com.lc.ibps.base.web.context.ContextUtil;
import com.lc.ibps.cloud.entity.APIResult;
import com.lc.ibps.components.httpclient.model.HttpStatus;
import com.lc.ibps.components.token.model.Token;
import com.lc.ibps.org.auth.persistence.entity.PartyWcappPo;
import com.lc.ibps.org.party.persistence.entity.DefaultPartyUserPo;
import com.lc.ibps.org.party.repository.DefaultPartyUserRepository;
import com.lc.ibps.org.partyWcapp.service.PartyWcappService;
import com.lc.ibps.platform.rest.token.TokenUtil;
import com.lc.ibps.web.controller.BaseApiController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import net.sf.json.JSONObject;
import net.sf.json.util.JSONUtils;

/**
 * 登陆验证,带token返回
 *
 * <pre>
 *  
 * 构建组：ibps-platform-webapi
 * 作者：zhongjh
 * 邮箱：zjh20140614@163.com
 * 日期：2017年7月12日-下午4:27:43
 * 版权：广州流辰信息技术有限公司版权所有
 * </pre>
 */
@RequestMapping(value = "/api/loginService")
@Api( value = "/loginService",tags = "系统管理-登陆服务")
@RestController("loginRest")
public class LoginController extends BaseApiController {

	/**
	 * 获取人员信息
	 *
	 * @param account
	 * @param pwd
	 * @param appid
	 * @param openid
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@ApiOperation(value = "app登录", notes = "app登录")
	@RequestMapping(value = "/appLogin", method = RequestMethod.POST)
	public APIResult<Map<String, Object>> appLogin(
			@ApiParam(name = "account", value = "用户账号", required = true) @RequestParam(name = "account", required = true) String account,
			@ApiParam(name = "pwd", value = "密码", required = true) @RequestParam(name = "pwd", required = true) String pwd,
			@ApiParam(name = "appid", value = "应用ID", required = false) @RequestParam(name = "appid", required = false) String appid,
			@ApiParam(name = "openid", value = "open ID", required = false) @RequestParam(name = "openid", required = false) String openid) {
		APIResult<Map<String, Object>> result = new APIResult<>();
		if (StringUtil.isEmpty(account) || StringUtil.isEmpty(pwd)) {
			result = getResult(result, HttpStatus.PRECONDITION_FAILED.value(), "用户名或密码错误!");
			return result;
		}

		DefaultPartyUserRepository defaultPartyUserRepository = AppUtil.getBean(DefaultPartyUserRepository.class);
		DefaultPartyUserPo user = defaultPartyUserRepository.getByAccount(account);
		if (BeanUtils.isEmpty(user)) {
			result = getResult(result, HttpStatus.PRECONDITION_FAILED.value(), "用户名或密码错误!");
			return result;
		}

		String encrptPassword = EncryptUtil.encryptSha256(pwd);
		if (!encrptPassword.equals(user.getPassword())) {
			result = getResult(result, HttpStatus.PRECONDITION_FAILED.value(), "用户名或密码错误!");
			return result;
		}

		try {
		
			ICache<String> cache = AppUtil.getBean(ICache.class);
			String token = TokenUtil.getTokenResult(AppUtil.getProperty("webapi.validCode"), Token.TOKEN_FORMAL)
					.getToken();
			// TODO 暂时用于旧版app，后面改造完删除
			String key = AppUtil.getAppid() + StringPool.COLON + user.getAccount();
			cache.add(key, token, 10 * 3600 * 24);

			// 加密key
			String userKey = TokenUtil.getKey(token);
			cache.add(userKey, account, 10 * 3600 * 24);// 用于token反向查找清除

			Map<String, Object> map = this.toMap(user);
			map.put("token", token);
			result.setData(map);

			if (StringUtil.isNotEmpty(openid)) {
				PartyWcappService partyWcappService = AppUtil.getBean(PartyWcappService.class);
				PartyWcappPo partyWcappPo = new PartyWcappPo();
				partyWcappPo.setUserid(user.getId());
				partyWcappPo.setAppid(appid);
				partyWcappPo.setOpenid(openid);
				partyWcappPo.setCreateTime(new Date());
				partyWcappService.save(JSONObject.fromObject(partyWcappPo).toString());
			}
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "登陆失败，请稍后再试！", e);
		}

		return result;
	}

	@SuppressWarnings({ "unchecked", "resource" })
	@ApiOperation(value = "微信登陆", notes = "微信登录")
	@RequestMapping(value = "/wcLogin", method = RequestMethod.POST)
	public APIResult<Map<String, Object>> wcLogin(
			@ApiParam(name = "wcAccount", value = "微信账号", required = false) @RequestParam(name = "wcAccount", required = false) String wcAccount,
			@ApiParam(name = "code", value = "微信随机code", required = false) @RequestParam(name = "code", required = false) String code) {

		APIResult<Map<String, Object>> result = new APIResult<>();

		List<NameValuePair> params = null;

		String userId = "";

		CloseableHttpResponse resp = null;

		CloseableHttpClient client = HttpClients.createDefault();

		if (StringUtils.isEmpty(wcAccount)) {
			try {
				// wechat token
				String getToken = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
				String access_token = "";
				params = new ArrayList<NameValuePair>();
				params.add(new BasicNameValuePair("corpid", AppUtil.getProperty("wechat.corpid")));
				params.add(new BasicNameValuePair("corpsecret", AppUtil.getProperty("wechat.corpsecret")));
				HttpGet get = new HttpGet(
						getToken + "?" + EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8)));
				resp = client.execute(get);
				if (resp.getStatusLine().getStatusCode() == HttpStatus.OK.value()) {
					HttpEntity entity = resp.getEntity();
					JSONObject res = JSONObject.fromObject(EntityUtils.toString(entity, "utf-8"));
					access_token = res.has("access_token") ? res.get("access_token").toString() : "";
				}

				if (StringUtil.isEmpty(access_token)) {
					result = getResult(result, FAIL, "获取access_token失败");
					return result;
				}

				// 微信登录用户信息
				String getUserInfo = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=" + access_token
						+ "&code=" + code;
				HttpPost post = new HttpPost(getUserInfo);
				resp = client.execute(post);
				if (resp.getStatusLine().getStatusCode() == HttpStatus.OK.value()) {
					HttpEntity entity = resp.getEntity();
					JSONObject res = JSONObject.fromObject(EntityUtils.toString(entity, "utf-8"));
					userId = res.has("UserId") ? res.get("UserId").toString() : "";
				}

				if (StringUtil.isEmpty(userId)) {
					result = getResult(result, FAIL, "获取userId失败");
					return result;
				}
			} catch (Exception e) {
				result = getExceptionResult(result, ERROR, "微信请求失败！", e);
				return result;
			} finally {
				try {
					if (client != null) {
						client.close();
					}
					if (resp != null) {
						resp.close();
					}
				} catch (IOException e) {
					throw new BaseException("关闭操作错误！");
				}
			}
		} else {
			userId = wcAccount;
		}

		// 获取系统用户信息
		DefaultPartyUserRepository defaultPartyUserRepository = AppUtil.getBean(DefaultPartyUserRepository.class);
		DefaultPartyUserPo user = defaultPartyUserRepository.getByWcAccount(userId);
		if (!BeanUtils.isEmpty(user)) {

			

			ICache<String> cache = AppUtil.getBean(ICache.class);
			String token = TokenUtil.getTokenResult(AppUtil.getProperty("webapi.validCode"), Token.TOKEN_FORMAL)
					.getToken();
			// TODO 暂时用于旧版app，后面改造完删除
			String key = AppUtil.getAppid() + StringPool.COLON + user.getAccount();
			cache.add(key, token, 10 * 3600 * 24);

			// 加密key
			String userKey = TokenUtil.getKey(token);
			cache.add(userKey, user.getAccount(), 10 * 3600 * 24);// 用于token反向查找清除

			Map<String, Object> map = this.toMap(user);
			map.put("token", token);
			result.setData(map);
		} else {
			result = getResult(result, FAIL, "用户不存在");
			return result;
		}

		return result;

	}
	
	@SuppressWarnings({ "unchecked", "resource" })
	@ApiOperation(value = "微信登陆", notes = "微信登录-面向公众号")
	@RequestMapping(value = "/wcLoginForOfficialAccount", method = RequestMethod.POST)
	public APIResult<Map<String, Object>> wcLoginForOfficialAccount(
			@ApiParam(name = "code", value = "微信随机code", required = false) @RequestParam(name = "code", required = false) String code) {
		APIResult<Map<String, Object>> result = new APIResult<>();
		List<NameValuePair> params = null;
		JSONObject employee = new JSONObject();
		CloseableHttpResponse resp = null;
		CloseableHttpClient client = HttpClients.createDefault();

		try {
			// wechat token
			String getToken = "https://api.weixin.qq.com/sns/oauth2/access_token";
			String access_token = "";
			String openId = "";
			params = new ArrayList<NameValuePair>();
			params.add(new BasicNameValuePair("appid", AppUtil.getProperty("wechat.appId")));
			params.add(new BasicNameValuePair("secret", AppUtil.getProperty("wechat.appSecret")));
			params.add(new BasicNameValuePair("code", code));
			params.add(new BasicNameValuePair("grant_type", "authorization_code"));
			HttpGet get = new HttpGet(
					getToken + "?" + EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8)));
			resp = client.execute(get);
			if (resp.getStatusLine().getStatusCode() == HttpStatus.OK.value()) {
				HttpEntity entity = resp.getEntity();
				JSONObject res = JSONObject.fromObject(EntityUtils.toString(entity, "utf-8"));
				access_token = res.has("access_token") ? res.get("access_token").toString() : "";
				openId = res.has("openid") ? res.get("openid").toString() : "";
			}

			if (StringUtil.isEmpty(access_token)) {
				result = getResult(result, FAIL, "获取access_token失败");
				return result;
			}

			// 获取用户信息
			String getUserInfo = "https://api.weixin.qq.com/sns/userinfo";
			params = new ArrayList<NameValuePair>();
			params.add(new BasicNameValuePair("access_token", access_token));
			params.add(new BasicNameValuePair("openid", openId));
			params.add(new BasicNameValuePair("lang", AppUtil.getProperty("wechat.lang")));
			get = new HttpGet(
					getUserInfo + "?" + EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8)));
			resp = client.execute(get);
			if (resp.getStatusLine().getStatusCode() == HttpStatus.OK.value()) {
				HttpEntity entity = resp.getEntity();
				JSONObject res = JSONObject.fromObject(EntityUtils.toString(entity, "utf-8"));
				
				createEmployee(employee, res);
			}
			
			if (JSONUtils.isNull(employee)) {
				result = getResult(result, FAIL, "获取用户信息失败");
				return result;
			}
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "微信请求失败！", e);
			return result;
		} finally {
			try {
				if (client != null) {
					client.close();
				}
				if (resp != null) {
					resp.close();
				}
			} catch (IOException e) {
				throw new BaseException("关闭操作错误！");
			}
		}
		
		// 创建用户
		IPartyEmployeeMgrService employeeService = AppUtil.getBean(IPartyEmployeeMgrService.class);
		employeeService.createEmployee(employee.toString());

		// 获取系统用户信息
		DefaultPartyUserRepository defaultPartyUserRepository = AppUtil.getBean(DefaultPartyUserRepository.class);
		DefaultPartyUserPo user = defaultPartyUserRepository.getByWcAccount(employee.getString("wcAccount"));
		if (!BeanUtils.isEmpty(user)) {

			ICache<String> cache = AppUtil.getBean(ICache.class);
			String token = TokenUtil.getTokenResult(AppUtil.getProperty("webapi.validCode"), Token.TOKEN_FORMAL)
					.getToken();

			// 加密key
			String userKey = TokenUtil.getKey(token);
			cache.add(userKey, user.getAccount(), 10 * 3600 * 24);// 用于token反向查找清除

			Map<String, Object> map = this.toMap(user);
			map.put("token", token);
			result.setData(map);
		} else {
			result = getResult(result, FAIL, "用户不存在");
			return result;
		}

		return result;
	}

	/**
	 * 
	 * 构造employee实体
	 *
	 * @param employee
	 * @param res
	 */
	private void createEmployee(JSONObject employee, JSONObject res) {
		String openid = res.has("openid") ? res.get("openid").toString() : "";
		String nickname = res.has("nickname") ? res.get("nickname").toString() : "";
		String sex = res.has("sex") ? res.get("sex").toString() : "";
		
		employee.put("account", openid);
		employee.put("password", "123456");
		employee.put("isSuper", "Y");
		employee.put("name", nickname);
		employee.put("status", "actived");
		employee.put("gender", "2".equals(sex) ? "female" : "male");
		employee.put("email", openid + "@abc.com");
		employee.put("wcAccount", openid);
	}
	

	@SuppressWarnings("unchecked")
	@ApiOperation(value = "登出", notes = "登出系统")
	@RequestMapping(value = "/logout", method = RequestMethod.POST)
	public APIResult<Map<String, Object>> logout() {
		APIResult<Map<String, Object>> result = new APIResult<>();
		try {
			ICache<String> cache = AppUtil.getBean(ICache.class);
			String token = ContextUtil.getCurrentAccessToken();
			String userKey = TokenUtil.getKey(token);
			cache.delByKey(userKey);
			ContextUtil.cleanAll();

			result.setMessage("成功登出系统！");
		} catch (Exception e) {
			result = getExceptionResult(result, ERROR, "登出系统失败！", e);
		}
		return result;
	}

	public Map<String, Object> toMap(DefaultPartyUserPo user) {
		Map<String, Object> userMap = new HashMap<>();
		userMap.put("account", user.getAccount());
		userMap.put("userId", user.getUserId());
		userMap.put("fullName", user.getFullname());
		return userMap;
	}

}
